#include "include/server.h"
#include "include/login.h"


// 启动服务器处理客户端的连接
int StartServer(char *ip,char *port){
    // 初始化Tcp连接
    int sockfd=InitTcpServer(ip,port);
    ERROR_CHECK(sockfd,-1,"InitTcpServer");
    // 初始化epoll
    int epfd=epoll_create(1);
    ERROR_CHECK(epfd,-1,"epoll_create");
    // 将监听sockfd加入监听
    AddEpoll(epfd,sockfd);
    struct epoll_event events[1024];
    // 创建线程池，最小线程4，最大线程16，队列的容量最大100
    ThreadPool *pool_short=threadPoolCreate(2,4,100);
    ERROR_CHECK(pool_short,NULL,"threadPoolCreate_short");
    ThreadPool *pool_long = threadPoolCreate(4,8,100);
    ERROR_CHECK(pool_long,NULL,"threadPoolCreate_long");
    //初始化主线程资源
    main_thread_resource_t main_resource;
    init_main_thread_resource(&main_resource);
    // 初始化数据库
    task_t *task = NULL;
    user_t user;
    MYSQL*db=InitDb("localhost","root","123456","CloudProject");
    ERROR_CHECK(db,NULL,"InitDb");
    while(1){
        printf("进入循环了\n");
        int readyNum = epoll_wait(epfd,events,1024,-1);
        for(int i=0;i<readyNum;i++){
            // 监听到sockfd连接
            if(events[i].data.fd == sockfd){
                // 有新的连接
                int netfd = accept(sockfd,NULL,NULL);
                task = task_init(netfd);
                //接收一个字节判断新的客户端还是读写子线程
                accept_info_t accept_info;
                memset(&accept_info,0,sizeof(accept_info_t));
                recv(netfd,&accept_info,sizeof(accept_info_t),MSG_WAITALL);
                if(accept_info.is_new == 0){//新连接建立
                    //登录或注册流程
                    printf("这个地方是注册或登录\n");
                    int ret = login_or_register(netfd,&accept_info,task,db,&user);
                    printf("---------\n");
                    if(ret == -1){
                        printf("登录或注册失败\n");
                        close(netfd);
                        continue;
                    }

                    //生成jwt密文并写入accept_info结构体中
                    jwt_encode(&accept_info,accept_info.username);
                    printf("jwt_encode:%s\n",accept_info.jwt);

                    //发送accept_info结构体给客户端
                    send(netfd,&accept_info,sizeof(accept_info_t),0);

                    // 将netfd加入监听
                    add_netfd_to_resource(&main_resource,netfd);

                    // 将netfe加入epoll监听中
                    AddEpoll(epfd,netfd);
                }else{//旧客户端的文件读写连接
                    printf("这个地方是旧客户端的文件读写连接\n");
                    //确认临时连接是否合法，并获取执行任务
                    task_t *get_task = (task_t* )malloc(sizeof(task_t));
                    get_task = accept_and_get_task(netfd,&accept_info);
                    //在线程池中寻找线程执行任务
                    threadPoolAdd(pool_long,client_thread_long,(void *)get_task);
                }
                continue;
            }

            //判断那个netfd传入任务
            for(int j=0;j<main_resource.netfd_count;j++){
                if(events[i].data.fd == main_resource.netfd[j])
                    //接收任务
                    task = task_init(main_resource.netfd[j]);

                    //接收命令小火车
                    recv(main_resource.netfd[j],&task->_train,sizeof(task->_train),0);

                    //根据任务决定使用哪个线程池
                    int cmd_type = judge_cmd_type(&task->_train);
                    printf("cmd_type:%d\n",cmd_type);
                    if(cmd_type == 0){
                        //进入短命令子线程
                        threadPoolAdd(pool_short,client_thread_short,(void *)task);
                    }else{
                        printf("无效命令\n");
                        continue;
                    }
            }
        }
    }
    threadPoolDestroy(pool_short);
    threadPoolDestroy(pool_long);
    close(sockfd);
    close(epfd);
    return 0;
}

